<?php

/**
* alltosun.com  index.php for newbd
* ============================================================================
* 版权所有 (C) 2009-2014 北京互动阳光科技有限公司，并保留所有权利。
* 网站地址: http://www.alltosun.com
* ----------------------------------------------------------------------------
* 许可声明: 这是一个开源程序，未经许可不得将本软件的整体或任何部分用于商业用途及再发布。
* ============================================================================
* Author: 吴松键 (wusj@alltosun.com)
* Date: 15/1/26 下午3:54
*/

class Action
{
    private $tenpay_config;

    public function __construct()
    {
        exit('当前支付不能使用');
        require_once MODULE_PATH.'/openapi/config/tenpay_config.php';

        $this->tenpay_config = array(
            'partner'        => Config::get('partner'),
            'key'            => Config::get('tenpay_key'),
            'input_charset'  => Config::get('input_charset'),
            'sign_type'      => Config::get('sign_type'),
            'gateway'        => Config::get('tenpay_gateway'),
            'cacert'         => Config::get('cacert'),
            'user_cert'      => Config::get('user_cert'),
            'cert_passwd'    => Config::get('cert_passwd')
        );
    }

    public function pay()
    {
        $order_id = Request::getParam('order_id', '');

        if (!$order_id) {
            return array('支付超时，请重新发起支付', 'error', AnUrl('order'));
        }

        $order_info = _uri('order', $order_id);
        if ($order_info['progress'] > 1) {
            return array('支付超时，请重新发起支付', 'error', AnUrl('order'));
        }

        $pay_args = array(
            'partner'          => $this->tenpay_config['partner'],
            'out_trade_no'     => order_helper::order_id_encode($order_id),
            //'total_fee'        => $order_info['price']*100,
            'total_fee'        => 1,
            'body'             => order_helper::get_goods_title($order_id),
            'notify_url'       => AnUrl('openapi/tenpay/pay_notify'),
            'return_url'       => AnUrl('openapi/tenpay/pay_return'),
            'spbill_create_ip' => get_ip(),
            'input_charset'    => $this->tenpay_config['input_charset'],
            'service_version'  => '1.0',
            'fee_type'         => '1'
        );

        $request_string = $this->build_request_param_string($pay_args);

        // Response::assign('pay_url', $this->tenpay_config['gateway']);
        // Response::assign('param', explode('&', $request_string));

        // Response::display(MODULE_PATH.'/openapi/template/pay_form.html');

        Response::redirect($this->tenpay_config['gateway'].'?'.$request_string);
    }

    public function refund()
    {
        require_once MODULE_PATH.'/openapi/helper/tenpay/tenpay_notify.class.php';

        $refund_id = Request::getParam('refund_id', 0);
        if (!$refund_id) {
            exit('请选择需要退款的订单');
        }

        $refund_info = _uri('refund', (int)$refund_id);
        if (!$refund_info || empty($refund_info)) {
            exit('请选择需要退款的订单');
        }
        _model('refund')->update(array('id'=>$refund_id), array('refund_pay_status'=>1));

        $order_info = _uri('refund', $refund_info['order_id']);

        //构造要请求的参数数组
        $refund_param = array(
            'partner'          => $this->tenpay_config['partner'],
            'transaction_id'   => $order_info['transaction_id'],
            'out_refund_no'    => order_helper::order_id_encode((int)$refund_id, 2),
            'total_fee'        => $order_info['price']*100,
            'refund_fee'       => $refund_info['price']*100,
            'op_user_id'       => $this->tenpay_config['op_user_id'],
            'op_user_passwd'   => md5($this->tenpay_config['op_user_passwd']),
            'input_charset'    => $this->tenpay_config['input_charset'],
            'sign_type'        => $this->tenpay_config['sign_type'],
            'service_version'  => '1.1'
        );
        /*
        //构造要请求的参数数组
        $refund_param = array(
            'partner'          => $this->tenpay_config['partner'],
            'transaction_id'   => '1900000109201501270360915982',
            'out_refund_no'    => '2015123412343920041',
            'total_fee'        => 1,
            'refund_fee'       => 1,
            'op_user_id'       => $this->tenpay_config['op_user_id'],
            'op_user_passwd'   => md5($this->tenpay_config['op_user_passwd']),
            'input_charset'    => $this->tenpay_config['input_charset'],
            'sign_type'        => $this->tenpay_config['sign_type'],
            'service_version'  => '1.1'
        );*/

        try {
            $tenpayNotify  = new TenpayNotify($this->tenpay_config);
            if (!$tenpayNotify->call($refund_param, 'refund')) {
                throw new Exception($tenpayNotify->getErrInfo());
            }

            $xml = $tenpayNotify->getResContent();
            $result_info = $this->xmlToArray($xml);

            if (!($tenpayNotify->getSignVeryfy($result_info, $result_info['sign']) && $result_info['retcode'] == 0)) {
                throw new Exception($result_info['retmsg']);
            }

            // 业务处理
            $transaction_refund_id = $result_info['refund_id_0'];
            $transaction_id = $result_info['transaction_id_0'];
            $order_id       = order_helper::order_id_decode($result_info['out_trade_no_0']);
            $refund_id      = order_helper::order_id_decode($result_info['out_refund_no_0']);
            $refund_fee     = $result_info['refund_fee_0'];

            $curr_info['transaction_id']  = $transaction_refund_id;
            $curr_info['refund_status'] = 0;
            $curr_info['refund_pay_status'] = 0;
            if ($result_info['refund_status_0'] == 4 || $result_info['refund_status_0'] == 10) {
                $curr_info['refund_status'] = 25;
                $curr_info['refund_pay_status'] = 2;
                $ret_msg = '财付通退款成功,此通知为异步通知';
            } elseif (in_array($result_info['refund_status_0'], array(3, 5, 6))) {
                $curr_info['refund_status'] = 23;
                $curr_info['refund_pay_status'] = 3;
                $ret_msg = '财付通退款失败';
            } elseif ($result_info['refund_status_0'] == 7) {
                $curr_info['refund_status'] = 23;
                $curr_info['refund_pay_status'] = 4;
                $ret_msg = '财付通退款失败，需要人工干预';
            }

            if ($curr_info['refund_status'] && $curr_info['refund_pay_status']) {
                _model('refund')->update(array('id'=>$refund_id, 'refund_status'=>20), $curr_info);

                // 发送退款完成短信
                $order_info = _uri('order', $order_id);
                $email = _uri('user', $order_info['user_id'], 'email');
                order_helper::sendExpressMessage('refund_success', array(order_helper::order_id_encode($order_info['id'])), $order_info['mobile'], $email);

                log_helper::create_refund_log('tenpay', array(
                    'transaction_id' => $transaction_id,
                    'order_id'       => $order_id,
                    'refund_id'      => $refund_id,
                    'transaction_refund_id' => $transaction_refund_id,
                    'refund_fee'     => $refund_fee,
                    'refund_status'  => 'success',
                    'ret_msg'        => $ret_msg
                ));
            }

            exit('ok');
        } catch (Exception $exp) {
            // 后台通知出错
            log_helper::create_refund_log('quickpay', array(
                'transaction_id' => '',
                'order_id'       => '',
                'refund_id'      => '',
                'transaction_refund_id' => '',
                'refund_fee'     => '',
                'refund_status'  => 'error',
                'ret_msg'        => '财付通退款失败：'.$exp->getMessage()
            ));

            exit('退款失败');
        }
    }

    /**
     * 退款批量查询
     */
    public function return_query()
    {
        $refund_id = Request::getParam('refund_id', $refund_id);
        if (!$refund_id) {
            exit('请选择需要退款的订单');
        }

        $refund_info = _uri('refund', (int)$refund_id);
        if (!$refund_info) {
            exit('当前退款订单不存在');
        }
        if ($refund_info['refund_pay_status'] == 2) {
            exit('ok'); // 退款已成)功
        }

        $query_param = array(
                'partner'   => $this->tenpay_config['partner'],
                'refund_id' => $refund_info['transaction_id']
            );
        try {
            $tenpayNotify  = new TenpayNotify($this->tenpay_config);
            if (!$tenpayNotify->call($query_param, 'refund_query')) {
                throw new Exception($tenpayNotify->getErrInfo());
            }

            $xml = $tenpayNotify->getResContent();
            $result_info = $this->xmlToArray($xml);

            if (!($tenpayNotify->getSignVeryfy($result_info, $result_info['sign']) && $result_info['retcode'] == 0)) {
                throw new Exception($result_info['retmsg']);
            }

            // 业务处理
            $transaction_refund_id = $result_info['refund_id_0'];
            $transaction_id = $result_info['transaction_id_0'];
            $order_id       = order_helper::order_id_decode($result_info['out_trade_no_0']);
            $refund_id      = order_helper::order_id_decode($result_info['out_refund_no_0']);
            $refund_fee     = $result_info['refund_fee_0'];

            if ($result_info['refund_status_0'] == 4) {
                $curr_info['refund_status'] = 25;
                $curr_info['refund_pay_status'] = 2;
            
                _model('refund')->update(array('id'=>$refund_id, 'refund_status'=>20), $curr_info);
                
                // 发送退款完成短信
                $order_info = _uri('order', $order_id);
                $email = _uri('user', $order_info['user_id'], 'email');
                order_helper::sendExpressMessage('refund_success', array(order_helper::order_id_encode($order_info['id'])), $order_info['mobile'], $email);

                log_helper::create_refund_log('tenpay', array(
                    'transaction_id' => $transaction_id,
                    'order_id'       => $order_id,
                    'refund_id'      => $refund_id,
                    'transaction_refund_id' => $transaction_refund_id,
                    'refund_fee'     => $refund_fee,
                    'refund_status'  => 'success',
                    'ret_msg'        => '财付通退款成功,此通知为异步通知'
                ));
                exit('ok');
            }

            exit('退款处理中');
        } catch (Exception $exp) {
            // 后台通知出错
            log_helper::create_refund_log('quickpay', array(
                'transaction_id' => '',
                'order_id'       => '',
                'refund_id'      => '',
                'transaction_refund_id' => '',
                'refund_fee'     => '',
                'refund_status'  => 'error',
                'ret_msg'        => '财付通退款失败：'.$exp->getMessage()
            ));

            exit('退款失败');
        }
    }

    /**
     * 财付通同步通知
     */
    public function pay_return()
    {
        require_once MODULE_PATH.'/openapi/helper/tenpay/tenpay_notify.class.php';
        try{
            $tenpayNotify  = new TenpayNotify($this->tenpay_config);
            $verify_result = $tenpayNotify->verifyNotify();
            if(!$verify_result) {
                throw new Exception($tenpayNotify->getErrInfo());
            }

            $result_info = $this->xmlToArray($tenpayNotify->getResContent());

            if (empty($result_info)) {
                throw new Exception('支付信息错误');
            }
            if ($result_info['retcode'] != 0) {
                throw new Exception($result_info['retmsg']);
            }

            $order_code     = $result_info['out_trade_no'];
            $order_id       = order_helper::order_id_decode($order_code);
            $transaction_id = $result_info['transaction_id'];
            $total_fee      = $result_info['total_fee']/100;
            $order_info     = _uri('order', (int)$order_id);

            if ($order_info['progress'] == 10) {
                return array('交易成功，等待商家发货！', 'error', AnUrl('order'));
            } else {
                return array('交易处理中，请耐心等待', 'error', AnUrl('order'));
            }

            /*
            $info['progress'] = 10;
            $info['transaction_id'] = $transaction_id;
            $info['pay_time']       = date('Y-m-d H:i:s', strtotime($result_info['time_end']));

            if ($total_fee != $order_info['price']) {
                throw new Exception("支付价格和订单价格不一致，存在非法获取行为！");
            }

            _model('order')->update(array('id'=>$order_id, 'progress'=>1), $info);

            log_helper::create_pay_log('tenpay', array(
                'transaction_id' => $transaction_id,
                'order_id'       => $order_id,
                'total_price'    => $total_fee,
                'trade_status'   => 'success',
                'remarks'        => '支付成功，当前通知为同步通知'
            ));

            return array('交易成功，等待商家发货！', 'error', AnUrl('order'));
            */
        } catch (Exception $exp) {
            log_helper::create_pay_log('tenpay', array(
                'transaction_id' => '',
                'order_id'       => '',
                'total_price'    => '',
                'trade_status'   => 'error',
                'remarks'        => '财付通支付失败:'.$exp->getMessage()
            ));

            return array($exp->getMessage(), 'error', AnUrl('order'));
        }
    }

    /**
     * 财付通异步通知
     */
    public function pay_notify()
    {
        require_once MODULE_PATH.'/openapi/helper/tenpay/tenpay_notify.class.php';
        try{
            $tenpayNotify  = new TenpayNotify($this->tenpay_config);
            $verify_result = $tenpayNotify->verifyNotify();
            if(!$verify_result) {
                throw new Exception($tenpayNotify->getErrInfo());
            }

            $result_info = $this->xmlToArray($tenpayNotify->getResContent());

            if (empty($result_info)) {
                throw new Exception('支付信息错误');
            }
            if ($result_info['retcode'] != 0) {
                throw new Exception($result_info['retmsg']);
            }

            $order_code     = $result_info['out_trade_no'];
            $order_id       = order_helper::order_id_decode($order_code);
            $transaction_id = $result_info['transaction_id'];
            $total_fee      = $result_info['total_fee']/100;
            $order_info     = _uri('order', (int)$order_id);
            $info['progress'] = 10;
            $info['transaction_id'] = $transaction_id;
            $info['pay_time']       = date('Y-m-d H:i:s', strtotime($result_info['time_end']));

            //if ($total_fee != $order_info['price']) {
            //    throw new Exception("支付价格和订单价格不一致，存在非法获取行为！");
            //}

            _model('order')->update(array('id'=>$order_id, 'progress'=>1), $info);

            log_helper::create_pay_log('tenpay', array(
                'transaction_id' => $transaction_id,
                'order_id'       => $order_id,
                'total_price'    => $total_fee,
                'trade_status'   => 'success',
                'remarks'        => '支付成功，当前通知为异步通知'
            ));

            exit('success');
        } catch (Exception $exp) {
            log_helper::create_pay_log('tenpay', array(
                'transaction_id' => '',
                'order_id'       => '',
                'total_price'    => '',
                'trade_status'   => 'error',
                'remarks'        => '财付通支付失败:'.$exp->getMessage()
            ));

            exit('fail');
        }
    }

    /**
     * 生成要请求给支付的参数数组
     * @param $para_temp 请求前的参数数组
     * @return 要请求的参数数组字符串
     */
    private function build_request_param_string($param_temp) {
        //待请求参数数组
        $param_filter = openapi_helper::param_filter($param_temp);

        //对待签名参数数组排序
        $param_sort = openapi_helper::param_sort($param_filter);

        //生成签名结果
        $mysign = openapi_helper::build_request_sign($param_sort, $this->tenpay_config['key'], 'tenpay');
        //签名结果与签名方式加入请求提交参数组中
        $param_sort['sign']      = $mysign;

        //把参数组中所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串，并对字符串做urlencode编码
        $request_data = http_build_query($param_sort);

        return $request_data;
    }

    /**
     * 	作用：将xml转为array
     */
    private function xmlToArray($xml)
    {
        //将XML转为array
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        if (!empty($array_data)) {
            foreach ($array_data as $k=>$v) {
                if (is_array($v) && empty($v)) {
                    $array_data[$k] = '';
                }
            }
        }

        return $array_data;
    }
}